<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.5.1 / SVN信息: $Id: class.File.php 2147 2009-12-16 03:14:37Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/

namespace JCAT\Common\FS ;

use JCAT\Core ;
use JCAT\Core\Assert ;
use JCAT\Core\Locale ;


// PHP 原生函数 fread 最大读取字节数
define('PHPORI_FREAD_MAXBYTE',8192) ;

/**
 * What's this Class ?
 *
 * @author		alee
 * @access		public
 * @last		2007.12.6
 */
class File extends FSO
{


	/**
	 * 构造函数
	 * 
	 * @access	public
	 * @param	$sPath				string	文件路径
	 * @param	$sOpenFlag=''		string	打开方式
	 * @param	$bAutoClose=true	bool	打开方式
	 * @return	void
	 */
	function File(  $sPath,  $sOpenFlag='', $bAutoClose=true ) 
	{
		$this->sPath = \JCAT\TidyPath($sPath) ;
		$this->bAutoClose = $bAutoClose ;
		$this->bFile = true ;
		
		if( $sOpenFlag )
		{
			if( !$this->Open($sOpenFlag) )
			{
				throw new Core\Exception(
						Locale\sx('无法打开文件：%s [Flag: %]',__NAMESPACE__,null,$sPath,$sOpenFlag)
						, __METHOD__, __LINE__, '$Revision: 2147 $'
				) ;
			}
		}
	}


	/**
	 * 析构函数
	 * 
	 * @access	public
	 * @return	void
	 */
	function __destruct()
	{
		// 自动关闭文件
		if( $this->hFile and $this->bAutoClose )
		{
			$this->Close() ;
		}
	}


	/**
	 * 获得文件的扩展名
	 * 
	 * @access	public
	 * @param	$nCase=0	int 大小写方式，0:原始; 1:大写返回; 2:小写返回
	 * @return	string
	 */
	public function GetExtName( $nCase=0 ) 
	{
		$sFileName = $this->GetName() ;
		if( !preg_match('/\./',$sFileName) )
		{
			return '' ;
		}
		
		$arr = explode('.',$sFileName) ;
		$sExtName = end($arr) ;
		
		if( $nCase==1 )
		{
			return strtoupper($sExtName) ;
		}
		elseif( $nCase==2 )
		{
			return strtolower($sExtName) ;
		}
		else
		{
			return $sExtName ;
		}
	}



	/**
	 * 获得文件名的标题部分
	 * 
	 * @access	public
	 * @return	string
	 */
	public function GetTitleName(  ) 
	{
		$sFileName = $this->GetName() ;
		if( !preg_match('/\./',$sFileName) )
		{
			return '' ;
		}
		
		$arr = explode('.',$sFileName) ;
		array_pop($arr) ;
		
		return implode('.',$arr) ;
	}



	/**
	 * 打开文件
	 * 
	 * @access	public
	 * @param	$sOpenFlag=''		string	打开方式
	 * @return	bool
	 */
	public function Open( $sOpenFlag ) 
	{
		$this->hFile = fopen($this->sPath,$sOpenFlag) ;
		if(!$this->hFile)
		{
			$this->hFile = null ;
			return false ;
		}
		
		else 
		{
			return true ;
		}
	}



	/**
	 * 关闭文件
	 * 
	 * @access	public
	 * @return	bool
	 */
	public function Close(  ) 
	{
		if($this->IsOpen())
		{
			if( fclose($this->hFile) )
			{
				$this->hFile = null ;
				return true ;
			}
			else
			{
				return false ;
			}
		}
		return true ;
	}

	
	/**
	 * 返回文件是否打开
	 *
	 * @access	public
	 * @return	bool
	 */
	public function IsOpen()
	{
		return $this->hFile===null ;
	}


	/**
	 * 从文件中读取指定字节到一个变量中，返回实际读取到的自己数
	 * 
	 * @access	public
	 * @param	&$sContent		string	内容
	 * @param	$nByte=1024		int		字节数
	 * @return	int
	 */
	public function ReadTo(&$sContent,$nByte=1024) 
	{
		// 检查 是否调用 Open
		Assert\IS_THESE( $this->hFile, array('handle') , Locale\sx('尚未打开文件，请先调用 JCAT_File::Open()',__NAMESPACE__,null)) ;
		
		$nLeave = $nByte ;
		$sContent = '' ;
		
		// 读取
		while( $nLeave>0 and !feof($this->hFile) ) 
		{
			$nThisTime = ( $nLeave > PHPORI_FREAD_MAXBYTE)?
							PHPORI_FREAD_MAXBYTE:
							$nLeave ;
			$nLeave-= $nThisTime ;
			
			$sContent.= fread($this->hFile,$nThisTime) ;
		}
		
		return strlen($sContent) ;
	}



	/**
	 * 写入内容到文件
	 * 
	 * @access	public
	 * @param	$sContent		string	内容
	 * @return	bool
	 */
	public function Write( $sContent ) 
	{
		// 检查 是否调用 Open
		Assert\IS_THESE( $this->hFile, array('handle'), Locale\sx('尚未打开文件，请先调用 JCAT_File::Open()',__NAMESPACE__,null) ) ;
		
		return (fwrite($this->hFile,$sContent)===false)? false: true ;
	}



	/**
	 * 读出所有内容
	 * 
	 * @access	public
	 * @return	string
	 */
	public function ReadAll(  ) 
	{
		// 检查 是否调用 Open
		Assert\IS_THESE( $this->hFile, 'handle', Locale\sx('尚未打开文件，请先调用 JCAT_File::Open()',__NAMESPACE__,null) ) ;
		
		$sContent = $sReaded = '' ;
		while( $this->ReadTo($sReaded) )
		{
			$sContent.= $sReaded ;
		}
		return $sContent ;
	}

	/**
	 * 输出文件的全部内容
	 *
	 * @access	public
	 * @param	$nReadBufSize=1024		int
	 * @param	$nStart=0				int
	 * @return	void
	 */
	public function PrintContent($nReadBufSize=1024,$nStart=0)
	{
		$hFile = $this->GetHandle() ;
		JCAT_ASSERT::ASSERT_($hFile,Locale\sx('文件尚未打开，请先调用 Open 方法打开文件。',__NAMESPACE__,null))  ;
		$this->Seek($nStart) ;
		
		while( ($sBuf=fread($hFile,$nReadBufSize)) )
		{
			print $sBuf ;
		}
	}
	
	/**
	 * 对文件进行锁定
	 * 
	 * @access	public
	 * @param	$nOperate		string	操作
	 * @param	$bWouldBlock	string	堵塞
	 * @return	
	 */
	public function Lock( $nOperate=LOCK_EX, $bWouldBlock=false ) 
	{
		// 检查 是否调用 Open
		Assert\IS_THESE( $this->hFile, 'handle', Locale\sx('尚未打开文件，请先调用 JCAT_File::Open()',__NAMESPACE__,null) ) ;
		
		return flock($this->hFile,$nOperate,$bWouldBlock) ;
	}



	/**
	 * 对文件解除锁定
	 * 
	 * @access	public
	 * @return	
	 */
	public function Unlock() 
	{
		// 检查 是否调用 Open
		Assert\IS_THESE( $this->hFile, 'handle', Locale\sx('尚未打开文件，请先调用 JCAT_File::Open()',__NAMESPACE__,null) ) ;
		
		return flock($this->hFile,LOCK_UN) ;
	}



	/**
	 * 设置文件读取的指针位置
	 * 
	 * @access	public
	 * @param	$nSeek		int		指针位置
	 * @param	$nFromPos	int		起始位置，SEEK_SET,SEEK_CUR,SEEK_END
	 * @return	int
	 */
	public function Seek( $nSeek, $nFromPos=SEEK_SET ) 
	{
		// 检查 是否调用 Open
		Assert\IS_THESE( $this->GetHandle(), 'handle', Locale\sx('尚未打开文件，请先调用 JCAT_File::Open()',__NAMESPACE__,null) ) ;
		
		return fseek( $this->GetHandle(), $nSeek, $nFromPos ) ;
	}

	/**
	 * 返回文件读写指针位置
	 * 
	 * @access	public
	 * @return	int
	 */
	public function GetPos() 
	{
		// 检查 是否调用 Open
		Assert\IS_THESE( $this->hFile, 'handle', Locale\sx('尚未打开文件，请先调用 JCAT_File::Open()',__NAMESPACE__,null) ) ;

		return ftell($this->hFile) ;
	}
	

	/**
	 * 返回文件長度
	 * 
	 * @access	public
	 * @param	$nUnit=1024		int 单位
	 * @return	float,int
	 */	
	public function GetByte( $nUnit=1024 )
	{
		JCAT_ASSERT::ASSERT_( $nUnit, Locale\sx('参数 $nUnit 不能为 0',__NAMESPACE__,null) ) ;
		$nLen = filesize( $this->GetPath() ) ;
		return ($nLen/$nUnit) ;		
	}
	


	public function GetHandle()
	{ return $this->hFile ; }


	// 属性 ///////////////////////////////////////////////////////////////////////////////

	private $hFile = null ;
	
	private $bAutoClose = true ;
}
?>